<template>
  <div class="page-box">

    <el-form class="search">
      <el-form-item label="商品标题">
        <el-input v-model="listModel.skuTitle" placeholder="商品标题关键字" clearable />
      </el-form-item>
      <el-form-item label="上下架">
        <el-select v-model="listModel.skuSaleable" placeholder="选择是否上下架" clearable>
          <el-option v-for="item in saleableList" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
      </el-form-item>
      <el-form-item label="是否有效">
        <el-select v-model="listModel.skuValid" placeholder="选择是否有效" clearable>
          <el-option v-for="item in validList" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
      </el-form-item>
      <el-form-item class="search-btn">
        <el-button type="primary" icon="Search" @click="pageSizeChange">搜索</el-button>
        <el-button icon="RefreshRight" @click="resetList">重置</el-button>
      </el-form-item>
    </el-form>

    <div class="head">
      <span class="title">商品SKU管理</span>
      <div class="toolbar">
        <el-button type="primary" icon="Plus" @click="addOrModify(null)">添加</el-button>
        <el-button type="primary" icon="Refresh" @click="fetchListData">刷新</el-button>
        <el-button type="danger" icon="Delete" @click="isShowDelDialog = true">批量删除</el-button>
      </div>
    </div>

    <div class="table">
      <el-table
          stripe
          v-loading="loading"
          :data="listData"
          row-key="id"
          @selection-change="selectionChange"
      >
        <el-table-column type="selection" width="30" />
        <el-table-column prop="skuTitle" label="商品名称" />
        <el-table-column prop="skuPrice" label="价格" width="120" />
        <el-table-column prop="skuStockNum" label="库存" width="80" />
        <el-table-column prop="spuSaleable" label="上/下架" #default="{ row }" width="70">
          <el-switch v-model="row.skuSaleable" @change="skuSaleableChange(row)" />
        </el-table-column>
        <el-table-column prop="spuValid" label="是否有效" #default="{ row }" width="80">
          <el-switch v-model="row.skuValid" @change="skuValidChange(row)" />
        </el-table-column>
        <el-table-column prop="updated" label="修改时间" width="138" />
        <el-table-column label="操作" fixed="right" width="160" align="center" #default="{ row }">
          <el-button type="primary" icon="Edit" @click="addOrModify(row)" />
          <el-button type="danger" icon="Delete" @click="del(row.id)" />
        </el-table-column>
      </el-table>
    </div>
    <el-pagination
        class="pagination"
        v-model:current-page="listModel.current"
        v-model:page-size="listModel.size"
        :page-sizes="[10, 30, 50, 100]"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
        @size-change="pageSizeChange"
        @current-change="fetchListData"
    />

    <el-drawer
        size="70%"
        :title="addOrModifyDrawerTitle"
        v-model="isShowAddOrModifyDrawer"
        direction="rtl"
        :before-close="addOrModifyDrawerClose"
        @opened="addOrModifyDrawerOpened(addOrModifyFormRef)"
    >
      <div class="form-content">
        <el-form ref="addOrModifyFormRef" label-width="120px" :model="addOrModifyModel" :rules="addOrModifyRules">
          <el-form-item label="标题" prop="skuTitle">
            <el-input v-model="addOrModifyModel.skuTitle" placeholder="商品标题" autocomplete="off" clearable />
          </el-form-item>
          <el-form-item label="价格" prop="skuPrice">
            <el-input v-model="addOrModifyModel.skuPrice" placeholder="商品价格，用户实际购买价格" autocomplete="off" clearable />
          </el-form-item>
          <el-form-item label="市场价">
            <el-input v-model="addOrModifyModel.skuMarketPrice" placeholder="商品市场价，展示用" autocomplete="off" clearable />
          </el-form-item>
          <el-form-item label="库存" prop="skuStockNum">
            <el-input v-model="addOrModifyModel.skuStockNum" placeholder="商品库存，-1表示不限制库存" autocomplete="off" clearable />
          </el-form-item>
          <el-form-item label="销量" prop="skuSaleNum">
            <el-input v-model="addOrModifyModel.skuSaleNum" placeholder="商品销量" autocomplete="off" clearable />
          </el-form-item>
          <el-form-item label="轮播图片">
            <my-picture-upload :params="{usage: 'goods'}" :file-list="fileList" @upload-success="uploadSuccess" @remove="removeFile" />
          </el-form-item>
          <el-form-item label="所属产品" prop="spuId">
            <el-select
                v-model="addOrModifyModel.spuId"
                placeholder="请输入产品关键字"
                :loading="loading"
                remote
                :remote-method="getSpuList"
                filterable
                style="width: 100%;"
                @change="spuChange"
                clearable>
              <el-option v-for="item in spuList" :key="item.id" :label="item.spuTitle" :value="item.id" />
            </el-select>
          </el-form-item>
          <el-form-item :label="spec.specName + '(搜索)'" v-for="(spec, specIndex) in searchSpecList" :key="spec.id">
            <el-tag v-for="(item, itemIndex) in spec.specItems" :key="item.id" :effect="item.effect" @click="specChange(specIndex, itemIndex, 1)">
              {{ item.specValue }}
            </el-tag>
          </el-form-item>
          <el-form-item :label="spec.specName" v-for="(spec, specIndex) in noSearchSpecList" :key="spec.id">
            <el-tag v-for="(item, itemIndex) in spec.specItems" :key="item.id" :effect="item.effect" @click="specChange(specIndex, itemIndex, 2)">
              {{ item.specValue }}
            </el-tag>
          </el-form-item>
          <el-form-item label="所选规格">
            <el-tag v-show="item.id" v-for="(item, index) in noSearchSelectedSpec" :key="index" effect="dark">
              {{ item.specValue }}
            </el-tag>
          </el-form-item>
          <el-form-item>
            <el-button style="width: 120px;" type="primary" :loading="loading" @click="doAddOrModify">
              {{ loading ? '正在提交 ...' : '提交' }}
            </el-button>
            <el-button style="width: 120px;" @click="addOrModifyDrawerClose">取消</el-button>
          </el-form-item>
        </el-form>
      </div>
    </el-drawer>

    <el-dialog
        v-model="isShowSkuSaleableDialog"
        title="提示"
        width="30%"
        :before-close="cancelChangeSkuSaleable"
    >
      <span>确定要{{ listCurrentRow.skuSaleable ? '上架' : '下架' }}吗？</span>
      <template #footer>
        <span>
          <el-button @click="cancelChangeSkuSaleable">取消</el-button>
          <el-button type="primary" @click="changeSkuSaleable">确定</el-button>
        </span>
      </template>
    </el-dialog>

    <el-dialog
        v-model="isShowSkuValidDialog"
        title="提示"
        width="30%"
        :before-close="cancelChangeSkuValid"
    >
      <span>确定要{{ listCurrentRow.skuValid ? '有效' : '无效' }}吗？</span>
      <template #footer>
        <span>
          <el-button @click="cancelChangeSkuValid">取消</el-button>
          <el-button type="primary" @click="changeSkuValid">确定</el-button>
        </span>
      </template>
    </el-dialog>

    <el-dialog
        v-model="isShowDelDialog"
        title="提示"
        width="30%"
        :before-close="delDialogClose"
    >
      <span>确定要删除吗？</span>
      <template #footer>
        <span>
          <el-button @click="delDialogClose">取消</el-button>
          <el-button type="primary" :loading="loading" @click="doDel">
            {{ loading ? '正在删除 ...' : '确定' }}
          </el-button>
        </span>
      </template>
    </el-dialog>

  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { GetListData, AddData, ModifyData, DeleteData, ModifySaleable, ModifyValid } from '@/api/goods/sku'
import { saleableList, validList, GetByTitle, GetVoById } from '@/api/goods/spu'
import { GetBySpu } from '@/api/goods/spec'
import MyPictureUpload from '@/components/MyPictureUpload/index.vue'

const loading = ref(false)
const listCurrentRow = ref()
const fileServerUrl = ref(import.meta.env.VITE_FILE_SERVER_URL)

const spuList = ref([])
const getSpuList = async query => {
  if (!query || query.trim().length <= 0) {
    return
  }
  loading.value = true
  const { code, message, data } = await GetByTitle(query)
  loading.value = false
  if (code !== 200) {
    ElMessage.error(message)
    return
  }
  spuList.value = data
}

/* 商品上下架开始 */
const isShowSkuSaleableDialog = ref(false)
const skuSaleableChange = row => {
  listCurrentRow.value = row
  isShowSkuSaleableDialog.value = true
}
const cancelChangeSkuSaleable = () => {
  listCurrentRow.value.skuSaleable = !listCurrentRow.value.skuSaleable
  isShowSkuSaleableDialog.value = false
}
const changeSkuSaleable = async () => {
  const { code, message } = await ModifySaleable({
    id: listCurrentRow.value.id,
    skuSaleable: listCurrentRow.value.skuSaleable ? 1 : 0,
  })
  if (code !== 200) {
    ElMessage.error(message)
    return
  }
  isShowSkuSaleableDialog.value = false
  ElMessage.success(message)
}
/* 商品上下架结束 */

/* 商品有效/无效开始 */
const isShowSkuValidDialog = ref(false)
const skuValidChange = row => {
  listCurrentRow.value = row
  isShowSkuValidDialog.value = true
}
const cancelChangeSkuValid = () => {
  listCurrentRow.value.skuValid = !listCurrentRow.value.skuValid
  isShowSkuValidDialog.value = false
}
const changeSkuValid = async () => {
  const { code, message } = await ModifyValid({
    id: listCurrentRow.value.id,
    skuValid: listCurrentRow.value.skuValid ? 1 : 0,
  })
  if (code !== 200) {
    ElMessage.error(message)
    return
  }
  isShowSkuValidDialog.value = false
  ElMessage.success(message)
}
/* 产品有效/无效结束 */

/* 列表开始 */
const total = ref(0)
const listModelData = {
  current: 1,
  size: Number(import.meta.env.VITE_PAGE_SIZE),
  skuTitle: '',
  skuSaleable: '',
  skuValid: '',
}
const listModel = ref({ ...listModelData })
const listData = ref([])

const selectionChange = arr => {
  delModel.value.ids = []
  arr.forEach(row => {
    delModel.value.ids.push(row.id)
  })
}

const fetchListData = async () => {
  if (loading.value) {
    return
  }
  loading.value = true
  const { code, message, data } = await GetListData(listModel.value)
  loading.value = false
  if (code !== 200) {
    ElMessage.error(message)
    return
  }
  data.records.forEach(item => {
    item.skuSaleable = item.skuSaleable === 1
    item.skuValid = item.skuValid === 1
  })
  listData.value = data.records
  total.value = Number(data.total)
}

const pageSizeChange = () => {
  listModel.value.current = 1
  fetchListData()
}

const resetList = () => {
  listModel.value = { ...listModelData }
  fetchListData()
}

onMounted(() => {
  fetchListData()
})
/* 列表结束 */

/* 上传图片开始 */
const fileList = ref([])
const uploadFileList = ref([]) // 最终的图片保存在这里

const uploadSuccess = file => {
  uploadFileList.value.push(file)
}

const removeFile = files => {
  uploadFileList.value = []
  files.forEach(item => {
    let name = item.name
    if (item.response) {
      name = item.response.data.name
    }
    uploadFileList.value.push(name)
  })
  ElMessage.success('删除成功')
}
/* 上传图片结束 */

/* 添加修改开始 */
const noSearchSelectedSpec = ref({})
const searchSpecList = ref([])
const noSearchSpecList = ref([])
const addOrModifyFormRef = ref()
const addOrModifyDrawerTitle = ref('')
const isShowAddOrModifyDrawer = ref(false)

const addOrModifyData = {
  spuId: '',
  skuTitle: '',
  skuPrice: '',
  skuMarketPrice: '',
  skuImages: null,
  skuStockNum: '',
  skuSaleNum: 1,
  skuSpec: '',
  skuSpecList: [],
}
const addOrModifyModel = ref({ ...addOrModifyData })

const addOrModifyRules = ref({
  spuId: [{ required: true, message: '请选择产品SPU', trigger: 'blur' }],
  skuTitle: [{ required: true, message: '请输入商品标题', trigger: 'blur' }],
  skuPrice: [{ required: true, message: '请输入商品价格', trigger: 'blur' }],
  skuStockNum: [{ required: true, message: '请输入商品库存', trigger: 'blur' }],
  skuSaleNum: [{ required: true, message: '请输入商品销量', trigger: 'blur' }],
  skuSpec: [{ required: true, message: '请选择商品规格', trigger: 'blur' }],
})

const spuChange = async () => {
  const { code, message, data } = await GetBySpu(addOrModifyModel.value.spuId)
  if (code !== 200) {
    ElMessage.error(message)
    return
  }
  if (addOrModifyModel.value.skuSpecList.length <= 0) {
    addOrModifyModel.value.skuSpecList = new Array(data.searchSpecList.length)
  }
  data.searchSpecList.forEach((spec, specIndex) => {
    const curSpec = addOrModifyModel.value.skuSpecList[specIndex]
    spec.specItems.forEach(item => {
      if (curSpec && curSpec.specItemId === item.id) {
        item.effect = 'dark'
      } else {
        item.effect = 'light'
      }
    })
  })
  data.noSearchSpecList.forEach(spec => {
    const curSpec = noSearchSelectedSpec.value[spec.id]
    spec.specItems.forEach(item => {
      if (curSpec && curSpec.id === item.id) {
        item.effect = 'dark'
      } else {
        item.effect = 'light'
      }
    })
  })
  searchSpecList.value = data.searchSpecList
  noSearchSpecList.value = data.noSearchSpecList
}

const specChange = (specIndex, itemIndex, t) => {
  if (t === 1) {
    searchSpecList.value.forEach((spec, sIndex) => {
      if (specIndex === sIndex) {
        spec.specItems.forEach(item =>
            item.effect = 'light'
        )
      }
    })
    const currentSpec = searchSpecList.value[specIndex];
    const currentSpecItem = currentSpec.specItems[itemIndex]
    if (addOrModifyModel.value.id && addOrModifyModel.value.id > 0) {
      addOrModifyModel.value.skuSpecList[specIndex] = {
        skuId: addOrModifyModel.value.id,
        specId: currentSpec.id,
        specItemId: currentSpecItem.id
      }
    } else {
      addOrModifyModel.value.skuSpecList[specIndex] = {
        specId: currentSpec.id,
        specItemId: currentSpecItem.id
      }
    }
    currentSpecItem.effect = 'dark'
  } else {
    noSearchSpecList.value.forEach((spec, sIndex) => {
      if (specIndex === sIndex) {
        spec.specItems.forEach(item =>
            item.effect = 'light'
        )
      }
    })
    const currentSpec = noSearchSpecList.value[specIndex]
    const currentSpecItem = currentSpec.specItems[itemIndex]
    noSearchSelectedSpec.value[currentSpec.id] = {
      id: currentSpecItem.id,
      specName: currentSpec.specName,
      specValue: currentSpecItem.specValue
    }
    currentSpecItem.effect = 'dark'
  }
}

const getSpu = async id => {
  const { code, message, data } = await GetVoById(id)
  if (code !== 200) {
    ElMessage.error(message)
    return
  }
  spuList.value = [data]
}

const addOrModify = row => {
  if (row == null) {
    addOrModifyDrawerTitle.value = '添加商品SKU'
  } else {
    getSpu(row.spuId)
    noSearchSelectedSpec.value = JSON.parse(row.skuSpec)
    addOrModifyDrawerTitle.value = '编辑商品SKU'
    addOrModifyModel.value = { ...row }
    delete addOrModifyModel.value.created
    delete addOrModifyModel.value.updated
    delete addOrModifyModel.value.skuSaleable
    delete addOrModifyModel.value.skuValid
    const skuImages = JSON.parse(row.skuImages).facade
    if (skuImages.length > 0) {
      skuImages.forEach(item => {
        uploadFileList.value.push(item)
        fileList.value.push({
          name: item,
          url: `${fileServerUrl.value}${item}`
        })
      })
    }
    spuChange()
  }
  isShowAddOrModifyDrawer.value = true
}

const doAddOrModify = () => {
  if (loading.value) {
    return
  }
  addOrModifyModel.value.skuSpec = JSON.stringify(noSearchSelectedSpec.value)
  if (uploadFileList.value.length > 0) {
    addOrModifyModel.value.skuImages = JSON.stringify({
      facade: uploadFileList.value
    })
  }
  addOrModifyFormRef.value.validate(async valid => {
    if (!valid) {
      return
    }
    loading.value = true
    let code, message
    if (addOrModifyModel.value.id && addOrModifyModel.value.id > 0) {
      const result = await ModifyData(addOrModifyModel.value)
      code = result.code
      message = result.message
    } else {
      const result = await AddData(addOrModifyModel.value)
      code = result.code
      message = result.message
    }
    loading.value = false
    if (code !== 200) {
      ElMessage.error(message)
      return
    }
    isShowAddOrModifyDrawer.value = false
    resetAddOrModify()
    await fetchListData()
    ElMessage.success(message)
  })
}

const addOrModifyDrawerOpened = formEl => {
  formEl.clearValidate()
}

const resetAddOrModify = () => {
  fileList.value = []
  uploadFileList.value = []
  addOrModifyModel.value.skuImages = null
  if (addOrModifyModel.value.id && addOrModifyModel.value.id > 0) {
    searchSpecList.value = []
    noSearchSpecList.value = []
    noSearchSelectedSpec.value = {}
    addOrModifyFormRef.value.resetFields()
    addOrModifyModel.value = { ...addOrModifyData }
  }
  loading.value = false
}

const addOrModifyDrawerClose = () => {
  if (loading.value) {
    return
  }
  resetAddOrModify()
  isShowAddOrModifyDrawer.value = false
}
/* 添加修改结束 */

/* 删除开始 */
const isShowDelDialog = ref(false)
const delModel = ref({ ids: [] })

const del = id => {
  delModel.value.ids.push(id)
  isShowDelDialog.value = true
}

const doDel = async () => {
  if (loading.value) {
    return
  }
  if (delModel.value.ids.length <= 0) {
    ElMessage.error('请至少选择一项')
    return
  }
  loading.value = true
  const { code, message } = await DeleteData(delModel.value)
  loading.value = false
  if (code !== 200) {
    ElMessage.error(message)
    return
  }
  isShowDelDialog.value = false
  resetDel()
  await fetchListData()
  ElMessage.success(message)
}

const resetDel = () => {
  delModel.value.ids = []
  loading.value = false
}

const delDialogClose = () => {
  if (loading.value) {
    return
  }
  resetDel()
  isShowDelDialog.value = false
}
/* 删除结束 */
</script>

<style scoped lang="scss">
.page-box {
  width: 100%;
  box-sizing: border-box;
  .search {
    padding: 20px 20px 0;
    background: #fff;
    margin-bottom: 10px;
    display: flex;
    flex-wrap: wrap;
    .el-form-item {
      margin: {
        right: 10px;
        bottom: 20px;
      }
    }
    .search-btn {
      margin-left: auto;
    }
    :deep(.el-input-number .el-input__inner) {
      text-align: left;
    }
    :deep(.el-range-editor.el-input__wrapper) {
      box-sizing: border-box;
    }
  }
  .head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 20px 20px 0;
    background: #fff;
    .title {
      font-size: 16px;
    }
  }
  .table {
    padding: 20px;
    background: #fff;
  }
  .pagination {
    padding: 0 20px 20px;
    background: #fff;
    justify-content: flex-end;
    :last-child {
      margin-right: 0;
    }
  }
  .form-content {
    :deep(.el-tag) {
      margin: {
        right: 10px;
      }
      &:hover {
        cursor: pointer;
      }
    }
  }
}
</style>